use std::collections::HashMap;
use std::sync::Mutex;
use once_cell::sync::Lazy;
use regex::Regex;
use serde::{Deserialize, Serialize};
use swc_core::ecma::ast::{Module, ModuleItem, Stmt, Expr, CallExpr, Callee, Ident};
use swc_core::ecma::visit::{Visit, VisitWith};
use swc_core::common::{DUMMY_SP, SourceMap, FileName};
use swc_core::ecma::parser::{Parser, Syntax, TsConfig};
use swc_core::ecma::codegen::{Emitter, text_writer::JsWriter};

// 缓存结构，用于存储已处理的文件
static PROCESSED_FILES: Lazy<Mutex<HashMap<String, Option<String>>>> = Lazy::new(|| {
    Mutex::new(HashMap::new())
});

// 文件正则表达式缓存
static FILE_REGEX_CACHE: Lazy<Mutex<HashMap<String, Regex>>> = Lazy::new(|| {
    let mut map = HashMap::new();
    // 预先添加默认正则表达式
    map.insert(default_file_regex(), Regex::new(r"\.(js|jsx|ts|tsx)$").unwrap());
    Mutex::new(map)
});

// 配置结构
#[derive(Debug, Deserialize)]
pub struct PluginConfig {
    #[serde(default = "default_file_regex")]
    pub file_regex: String,
    
    #[serde(default = "default_import_prefix")]
    pub import_prefix: String,
    
    #[serde(default = "default_handle_dynamic_require")]
    pub handle_dynamic_require: bool,
    
    #[serde(default = "default_cache_size")]
    pub cache_size: usize,
}

fn default_file_regex() -> String {
    r"\.(js|jsx|ts|tsx)$".to_string()
}

fn default_import_prefix() -> String {
    "_vite_plugin_require_".to_string()
}

fn default_handle_dynamic_require() -> bool {
    false
}

fn default_cache_size() -> usize {
    500
}

// 实现默认配置
impl Default for PluginConfig {
    fn default() -> Self {
        Self {
            file_regex: default_file_regex(),
            import_prefix: default_import_prefix(),
            handle_dynamic_require: default_handle_dynamic_require(),
            cache_size: default_cache_size(),
        }
    }
}

// 预编译正则表达式，避免重复创建
static STATIC_REQUIRE_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r#"require\((['"])([^'"]+)\1\)"#).unwrap()
});

static DYNAMIC_REQUIRE_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r#"require\((['"])([^'"]+)\1\)|require\(`([^`]+)`\)"#).unwrap()
});

static PATH_TO_NAME_REGEX: Lazy<Regex> = Lazy::new(|| {
    Regex::new(r"(.*\/)*([^.]+).*").unwrap()
});

// 主要转换函数
pub fn transform_code(code: &str, id: &str, config: &PluginConfig) -> Result<String, String> {
    // 检查文件是否需要处理，使用缓存的正则表达式
    let file_regex = {
        let mut cache = FILE_REGEX_CACHE.lock().unwrap();
        if !cache.contains_key(&config.file_regex) {
            let regex = Regex::new(&config.file_regex).map_err(|e| e.to_string())?;
            cache.insert(config.file_regex.clone(), regex);
        }
        cache.get(&config.file_regex).unwrap().clone()
    };
    
    if !file_regex.is_match(id) {
        return Ok(code.to_string());
    }

    // 快速检查是否包含 require 关键字
    if !code.contains("require(") {
        return Ok(code.to_string());
    }

    // 检查缓存
    let cache_key = format!("{}:{}:{}", id, code.len(), &code[..100.min(code.len())]);
    {
        let cache = PROCESSED_FILES.lock().unwrap();
        if let Some(cached_result) = cache.get(&cache_key) {
            return match cached_result {
                Some(result) => Ok(result.clone()),
                None => Ok(code.to_string()),
            };
        }
    }

    // 使用预编译的正则表达式查找所有 require 调用
    let require_regex = if config.handle_dynamic_require {
        &*DYNAMIC_REQUIRE_REGEX
    } else {
        &*STATIC_REQUIRE_REGEX
    };

    let mut matches = Vec::new();
    for cap in require_regex.captures_iter(code) {
        let path = cap.get(2).or_else(|| cap.get(3)).map(|m| m.as_str().to_string());
        if let Some(path) = path {
            matches.push((path, cap.get(0).unwrap().as_str().to_string(), cap.get(0).unwrap().start()));
        }
    }

    if matches.is_empty() {
        // 没有找到 require 调用，更新缓存并返回原代码
        let mut cache = PROCESSED_FILES.lock().unwrap();
        cache.insert(cache_key, None);
        limit_cache_size(&mut cache, config.cache_size);
        return Ok(code.to_string());
    }

    // 收集唯一的导入路径
    let mut unique_paths = std::collections::HashSet::new();
    for (path, _, _) in &matches {
        unique_paths.insert(path.clone());
    }

    // 为每个路径生成导入语句
    let mut import_lines = Vec::new();
    let mut import_names = HashMap::new();

    for (i, path) in unique_paths.iter().enumerate() {
        let safe_path = path.replace(|c: char| c == '@' || c == '/' || c == '.' || c == '-', "_");
        let import_name = format!("{}{}_{}_{}", config.import_prefix, path_to_name(path), safe_path, i);
        import_names.insert(path.clone(), import_name.clone());
        import_lines.push(format!("import * as {} from \"{}\";", import_name, path));
    }

    // 生成导入代码
    let import_code = import_lines.join("\n") + "\n";

    // 替换所有 require 调用
    let mut replacements = Vec::new();
    for (path, full, index) in matches {
        let name = import_names.get(&path).unwrap();
        replacements.push((index, index + full.len(), format!("({}.default || {})", name, name)));
    }

    // 从后向前排序
    replacements.sort_by(|a, b| b.0.cmp(&a.0));

    // 执行替换
    let mut transformed_code = code.to_string();
    if replacements.len() == 1 {
        let (start, end, replacement) = &replacements[0];
        transformed_code = format!("{}{}{}", 
            &transformed_code[..*start], 
            replacement, 
            &transformed_code[*end..]);
    } else if replacements.len() > 1 {
        let mut parts = Vec::new();
        let mut last_end = transformed_code.len();

        for (start, end, replacement) in replacements {
            parts.insert(0, &transformed_code[end..last_end]);
            parts.insert(0, &replacement);
            last_end = start;
        }

        if last_end > 0 {
            parts.insert(0, &transformed_code[..last_end]);
        }

        transformed_code = parts.join("");
    }

    // 将导入语句添加到文件顶部
    transformed_code = import_code + &transformed_code;

    // 更新缓存
    let mut cache = PROCESSED_FILES.lock().unwrap();
    cache.insert(cache_key, Some(transformed_code.clone()));
    limit_cache_size(&mut cache, config.cache_size);

    Ok(transformed_code)
}

// 辅助函数：将路径转换为变量名
fn path_to_name(path: &str) -> String {
    // 使用预编译的正则表达式
    if let Some(caps) = PATH_TO_NAME_REGEX.captures(path) {
        if let Some(name) = caps.get(2) {
            return name.as_str().replace("-", "_");
        }
    }
    "module".to_string()
}

// 辅助函数：限制缓存大小
fn limit_cache_size(cache: &mut HashMap<String, Option<String>>, max_size: usize) {
    if cache.len() > max_size {
        if let Some(key) = cache.keys().next().cloned() {
            cache.remove(&key);
        }
    }
}

// Wasm 导出函数，用于与 JavaScript 交互
#[cfg(feature = "wasm")]
#[wasm_bindgen::prelude::wasm_bindgen]
pub fn transform(code: &str, id: &str, config_json: &str) -> Result<String, String> {
    let config: PluginConfig = serde_json::from_str(config_json).map_err(|e| e.to_string())?;
    transform_code(code, id, &config)
}